package com.example.xunai.service.conversation.impl;

import com.example.xunai.dto.request.ai.ChatRequest;
import com.example.xunai.dto.request.conversation.CreateConversationRequest;
import com.example.xunai.dto.request.conversation.UpdateConversationRequest;
import com.example.xunai.dto.response.conversation.ConversationResponse;
import com.example.xunai.dto.response.conversation.ConversationListResponse;
import com.example.xunai.dto.response.conversation.MessageResponse;
import com.example.xunai.entity.Conversation;
import com.example.xunai.entity.ConversationMessage;
import com.example.xunai.repository.ConversationRepository;
import com.example.xunai.repository.ConversationMessageRepository;
import com.example.xunai.service.cache.CacheService;
import com.example.xunai.service.conversation.ConversationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class ConversationServiceImpl implements ConversationService {

    private final ConversationRepository conversationRepository;
    private final ConversationMessageRepository conversationMessageRepository;
    private final CacheService cacheService;

    @Override
    public Conversation getConversation(ChatRequest request) {
        if (request.getConversationId() != null) {
            return getConversationById(request.getUserId(), request.getConversationId());
        }
        return null;
    }

    @Override
    public ConversationListResponse getUserConversationsResponse(Long userId, Integer page, Integer size) {
        List<Conversation> conversations = conversationRepository.findByUserIdOrderByUpdateTimeDesc(userId);

        // 分页逻辑
        int totalCount = conversations.size();
        int fromIndex = (page - 1) * size;
        int toIndex = Math.min(fromIndex + size, totalCount);

        if (fromIndex >= totalCount) {
            return ConversationListResponse.empty(page, size);
        }

        List<Conversation> pagedConversations = conversations.subList(fromIndex, toIndex);

        // 转换为ConversationResponse列表
        List<ConversationResponse> conversationResponses = pagedConversations.stream()
                .map(this::convertToResponse)
                .collect(Collectors.toList());

        return ConversationListResponse.of(conversationResponses, totalCount, page, size);
    }

    @Override
    public ConversationResponse createConversation(CreateConversationRequest request) {
        try {
            Conversation conversation = new Conversation();
            conversation.setUserId(request.getUserId());
            conversation.setTitle(request.getTitle());
            conversation.setSessionId(request.getSessionId());
            conversation.setModel(request.getModel() != null ? request.getModel() : "deepseek");

            Conversation savedConversation = conversationRepository.save(conversation);

            // 缓存对话
            cacheService.cacheConversation(savedConversation);

            log.info("成功创建对话，ID: {}, 用户ID: {}, 标题: {}, 模型: {}",
                    savedConversation.getId(), request.getUserId(), request.getTitle(), request.getModel());

            return convertToResponse(savedConversation);
        } catch (Exception e) {
            log.error("创建对话失败，用户ID: {}, 标题: {}, 模型: {}, 错误: {}",
                    request.getUserId(), request.getTitle(), request.getModel(), e.getMessage(), e);
            throw new RuntimeException("创建对话失败: " + e.getMessage());
        }
    }

    @Override
    public Conversation getConversationBySessionId(String sessionId) {
        return conversationRepository.findBySessionId(sessionId);
    }

    @Override
    public Conversation getConversationByUserIdAndSessionId(Long userId, String sessionId) {
        return conversationRepository.findByUserIdAndSessionId(userId, sessionId);
    }

    @Override
    public Conversation getConversationById(Long userId, Long conversationId) {
        // 从缓存获取对话
        Conversation cachedConversation = cacheService.getCachedConversation(conversationId);
        if (cachedConversation != null) {
            if (cachedConversation.getUserId().equals(userId)) {
                log.debug("从缓存获取对话: {}", conversationId);
                return cachedConversation;
            } else {
                cacheService.evictConversationCache(conversationId);
            }
        }

        Conversation conversation = conversationRepository.findByUserIdAndId(userId, conversationId);
        if (conversation != null) {
            // 缓存对话
            cacheService.cacheConversation(conversation);
        }

        return conversation;
    }

    @Override
    public ConversationResponse getConversationResponseById(Long userId, Long conversationId) {
        Conversation conversation = getConversationById(userId, conversationId);
        return conversation != null ? convertToResponse(conversation) : null;
    }

    @Override
    public ConversationResponse updateConversation(Long conversationId, UpdateConversationRequest request) {
        try {
            Conversation conversation = conversationRepository.findById(conversationId)
                    .orElseThrow(() -> new RuntimeException("对话不存在"));

            boolean updated = false;

            if (request.hasTitle()) {
                conversation.setTitle(request.getTitle());
                updated = true;
                log.info("更新对话标题，对话ID: {}, 新标题: {}", conversationId, request.getTitle());
            }

            if (request.hasModel()) {
                // 验证是否可以更新模型
                List<ConversationMessage> messages = conversationMessageRepository.findByConversationIdOrderByTurnAsc(conversationId);
                if (!messages.isEmpty()) {
                    log.warn("对话已有消息，不允许修改模型，对话ID: {}, 当前模型: {}, 请求模型: {}",
                            conversationId, conversation.getModel(), request.getModel());
                    throw new RuntimeException("对话已有消息，不允许修改模型");
                }
                conversation.setModel(request.getModel());
                updated = true;
                log.info("更新对话模型，对话ID: {}, 新模型: {}", conversationId, request.getModel());
            }

            if (updated) {
                conversation.setUpdateTime(LocalDateTime.now());
                Conversation savedConversation = conversationRepository.save(conversation);

                // 缓存更新后的对话
                cacheService.cacheConversation(savedConversation);

                return convertToResponse(savedConversation);
            }

            return convertToResponse(conversation);
        } catch (Exception e) {
            log.error("更新对话失败，对话ID: {}, 错误: {}", conversationId, e.getMessage(), e);
            throw new RuntimeException("更新对话失败: " + e.getMessage());
        }
    }

    @Override
    public void updateConversationTime(Long conversationId) {
        try {
            Conversation conversation = conversationRepository.findById(conversationId)
                    .orElseThrow(() -> new RuntimeException("对话不存在"));
            conversation.setUpdateTime(LocalDateTime.now());
            conversationRepository.save(conversation);

            // 缓存更新后的对话
            cacheService.cacheConversation(conversation);

            log.debug("成功更新对话时间，对话ID: {}", conversationId);
        } catch (Exception e) {
            log.error("更新对话时间失败，对话ID: {}, 错误: {}", conversationId, e.getMessage(), e);
        }
    }

    @Override
    public List<MessageResponse> getConversationMessageResponses(Long userId, Long conversationId) {
        Conversation conversation = getConversationById(userId, conversationId);
        if (conversation == null) {
            throw new RuntimeException("对话不存在或无权访问");
        }

        // 从缓存获取消息
        List<ConversationMessage> cachedMessages = cacheService.getCachedMessages(conversationId);
        if (cachedMessages != null) {
            log.debug("从缓存获取对话消息: {}, 消息数量: {}", conversationId, cachedMessages.size());
            return cachedMessages.stream()
                    .map(MessageResponse::fromEntity)
                    .collect(Collectors.toList());
        }

        List<ConversationMessage> messages = conversationMessageRepository.findByConversationIdOrderByTurnAsc(conversationId);

        // 缓存消息
        cacheService.cacheConversationMessages(conversationId, messages);

        return messages.stream()
                .map(MessageResponse::fromEntity)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void deleteConversation(Long userId, Long conversationId) {
        Conversation conversation = getConversationById(userId, conversationId);
        if (conversation == null) {
            throw new RuntimeException("对话不存在或无权访问");
        }

        try {
            conversationMessageRepository.deleteByConversationId(conversationId);
            conversationRepository.delete(conversation);

            // 清除对话缓存
            cacheService.evictConversationCache(conversationId);

            log.info("已删除对话，ID: {}, 用户ID: {}", conversationId, userId);
        } catch (Exception e) {
            log.error("删除对话失败，对话ID: {}, 用户ID: {}, 错误: {}", conversationId, userId, e.getMessage(), e);
            throw new RuntimeException("删除对话失败: " + e.getMessage());
        }
    }

    @Override
    public boolean validateConversationModel(Long conversationId, String requestedModel) {
        Conversation conversation = conversationRepository.findById(conversationId).orElse(null);
        if (conversation == null) {
            return false;
        }

        boolean isValid = conversation.getModel().equals(requestedModel);
        if (!isValid) {
            log.warn("对话模型不匹配，对话ID: {}, 对话模型: {}, 请求模型: {}",
                    conversationId, conversation.getModel(), requestedModel);
        }

        return isValid;
    }

    /**
     * 将Conversation实体转换为ConversationResponse
     */
    private ConversationResponse convertToResponse(Conversation conversation) {
        return ConversationResponse.builder()
                .id(conversation.getId())
                .title(conversation.getTitle())
                .model(conversation.getModel())
                .createTime(conversation.getCreateTime())
                .updateTime(conversation.getUpdateTime())
                .sessionId(conversation.getSessionId())
                .userId(conversation.getUserId())
                .build();
    }
}